package com.lu.filter;

import com.alibaba.fastjson.JSONObject;
import com.lu.model.constant.RedisKeyConstants;
import com.lu.model.entity.SysUser;
import com.lu.model.domain.LoginUser;
import com.lu.service.SysUserService;
import com.lu.utils.JwtUtils;
import io.jsonwebtoken.Claims;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

import javax.servlet.FilterChain;
import javax.servlet.ServletException;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * @Description: token校验
 *  - 该类继承自BasicAuthenticationFilter，在doFilterInternal方法中，
 *  - 从http头的Authorization 项读取token数据，然后用Jwts包提供的方法校验token的合法性。
 *  - 如果校验通过，就认为这是一个取得授权的合法请求
 * @Author: zhanglu
 * @Date: 2022/7/26 17:22
 */
public class JwtAuthenticationFilter extends BasicAuthenticationFilter {

  private SysUserService userService;
  private RedisTemplate<String, Object> redisTemplate;

  public JwtAuthenticationFilter(AuthenticationManager authenticationManager, SysUserService userService, RedisTemplate<String, Object> redisTemplate) {
    super(authenticationManager);
    this.userService=userService;
    this.redisTemplate = redisTemplate;
  }

  @Override
  protected void doFilterInternal(HttpServletRequest request, HttpServletResponse response, FilterChain chain) throws IOException, ServletException {
    if(request.getHeader("access_token").equals("lu-boot-xxl-job-admin")){
      UsernamePasswordAuthenticationToken usernamePasswordAuthenticationToken = new UsernamePasswordAuthenticationToken(null, null, null);
      SecurityContextHolder.getContext().setAuthentication(usernamePasswordAuthenticationToken);
      chain.doFilter(request, response);
      return;
    }
    UsernamePasswordAuthenticationToken authentication = getAuthentication(request);
    if(authentication == null){
      SecurityContextHolder.clearContext();
      chain.doFilter(request, response);
      return;
    }
    SecurityContextHolder.getContext().setAuthentication(authentication);
    SysUser sysUser = null;
    try {
      sysUser = (SysUser) SecurityContextHolder.getContext().getAuthentication().getPrincipal();
    } catch (Exception e) {}
    if(sysUser == null){
      SecurityContextHolder.clearContext();
      chain.doFilter(request, response);
    }else {
      chain.doFilter(request, response);
    }
  }

  private UsernamePasswordAuthenticationToken getAuthentication(HttpServletRequest request) {
    try {
      String token = request.getHeader("access_token");
      if (token != null) {
        Claims claims = JwtUtils.verifyToken(token);
        Object userIdObj = claims.get("userId");
        if(userIdObj == null){
          return null;
        }
        Object loginUserObj = redisTemplate.opsForValue().get(RedisKeyConstants.loginUser(userIdObj));
        if(loginUserObj == null){
          return null;
        }
        LoginUser loginUser = JSONObject.parseObject(loginUserObj.toString(), LoginUser.class);
        if(loginUser == null){
          return null;
        }
        return new UsernamePasswordAuthenticationToken(loginUser.getUser(), null, loginUser.getAuthorities());
      }
    } catch (Exception e) {
      e.printStackTrace();
    }
    return null;
  }

}


